﻿/*
 *  Copyright (c) 2012 Brandon Ellenberger
 *
 *  This file is part of OpSatPlan.
 *
 *  OpSatPlan is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  OpSatPlan is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with OpSatPlan.  If not, see <http://www.gnu.org/licenses/>.
 */

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;

namespace OpSatPlan
{
    public class Domain
    {
        private string mName;
        private ReadOnlyCollection<ActionDefinition> mActionDefs;
        private ReadOnlyCollection<PredicateDefinition> mPredicateDefs;
        private ReadOnlyCollection<string> mRequirements;
        private ReadOnlyCollection<PddlType> mTypes;
        private Dictionary<string, PddlType> mTypeMap;
        private Dictionary<string, PredicateDefinition> mPredMap;

        public Domain(string name, IList<ActionDefinition> actions, IList<PredicateDefinition> preds,
                      IList<string> reqs, IList<PddlType> types)
        {
            Assertion.Assert<ArgumentNullException>(name != null, "Domain name cannot be null.");
            Assertion.Assert<UsageException>(name != string.Empty, "Domain name cannot be empty string.");
            this.mName = name.ToUpper();
            Assertion.Assert<ArgumentNullException>(actions != null, "Action Definition list cannot be null.");
            Assertion.Assert<UsageException>(actions.Count > 0, "Action Definitions cannot be empty.");
            this.mActionDefs = new ReadOnlyCollection<ActionDefinition>(actions);
            Assertion.Assert<ArgumentNullException>(preds != null, "Predicate Definition list cannot be null");
            Assertion.Assert<UsageException>(preds.Count > 0, "Predicate Definitions cannot be empty.");
            this.mPredicateDefs = new ReadOnlyCollection<PredicateDefinition>(preds);
            Assertion.Assert<ArgumentNullException>(reqs != null, "Requirements list cannot be null.");
            this.mRequirements = new ReadOnlyCollection<string>(reqs);
            Assertion.Assert<ArgumentNullException>(types != null, "Types list cannot be null.");
            this.mTypes = new ReadOnlyCollection<PddlType>(types);
            
            this.mTypeMap = new Dictionary<string, PddlType>();
            foreach(PddlType t in types)
                this.mTypeMap.Add(t.Name, t);

            this.mPredMap = new Dictionary<string, PredicateDefinition>();
            foreach (PredicateDefinition p in preds)
                this.mPredMap.Add(p.Name, p);
        }
        public string Name
        {
            get
            {
                return this.mName;
            }
        }
        public ReadOnlyCollection<ActionDefinition> ActionDefinitions
        {
            get
            {
                return this.mActionDefs;
            }
        }
        public ReadOnlyCollection<PredicateDefinition> PredicateDefinition
        {
            get
            {
                return this.mPredicateDefs;
            }
        }
        public ReadOnlyCollection<PddlType> Types
        {
            get
            {
                return this.mTypes;
            }
        }
        public ReadOnlyCollection<string> Requirements
        {
            get
            {
                return this.mRequirements;
            }
        }
        public PredicateDefinition GetPredicateByName(string name)
        {
            Assertion.Assert<UsageException>(this.mPredMap.ContainsKey(name), "Predicate " + name + " does not exist");
            return this.mPredMap[name];
        }
        public PddlType GetTypeByName(string name)
        {
            Assertion.Assert<UsageException>(this.mTypeMap.ContainsKey(name), "Type " + name + " does not exist");
            return this.mTypeMap[name];
        }
    }
}
